/*! \file parentdata.h
	\author HiddenSeeker
	
	Describes a parent data for creation of objects
*/
#include <vector>
class SemanticVisitorData;
class ClassSemantic;
struct Method;
class OperatorNode;
class AttributeAccess;
class Field;
class ConstantTable;
class JBFile;
#pragma once

class ParentData
{
friend class CurrentOperatorPtr;
friend class CurrentAccessPtr;
private:
	std::vector<OperatorNode *>        CurrentOperator;
	std::vector<AttributeAccess *>        CurrentAccess;

	inline void popOp()
	{
		CurrentOperator.erase(CurrentOperator.begin()+CurrentOperator.size()-1);
	}
	inline void popAcc()
	{
		CurrentAccess.erase(CurrentAccess.begin()+CurrentAccess.size()-1);
	}
public:
	SemanticVisitorData * Classes;
	ClassSemantic       * CurrentClass;
	Method              * CurrentMethod;
	Field               * CurrentField;
	inline void setCurrentAccess(AttributeAccess * acc)
	{
		CurrentAccess.push_back(acc);
	}
	inline void setCurrentOperator(OperatorNode * acc)
	{
		CurrentOperator.push_back(acc);
	}
	inline void getOp(CurrentOperatorPtr & ptr);
	inline void getAcc(CurrentAccessPtr & ptr);

	ConstantTable * currentTable();
	JBFile        * currentFile();
	inline ParentData() {}
};


class CurrentOperatorPtr
{
 friend class ParentData;
 private:
		ParentData * parent;
 public:
	    inline CurrentOperatorPtr()
		{
			parent=NULL;
		}
		OperatorNode * operator->() const
		{
			return parent->CurrentOperator[parent->CurrentOperator.size()-1];
		}
		OperatorNode & operator*() const
		{
			return *(parent->CurrentOperator[parent->CurrentOperator.size()-1]);
		}
		inline ~CurrentOperatorPtr()
		{
			if (parent)
				parent->popOp();
		}
};

class CurrentAccessPtr
{
 friend class ParentData;
 private:
		ParentData * parent;
 public:
	    inline CurrentAccessPtr()
		{
			parent=NULL;
		}
		AttributeAccess * operator->() const
		{
			return parent->CurrentAccess[parent->CurrentAccess.size()-1];
		}
		AttributeAccess & operator*() const
		{
			return *(parent->CurrentAccess[parent->CurrentAccess.size()-1]);
		}
		inline ~CurrentAccessPtr()
		{
			if (parent)
				parent->popAcc();
		}
};

inline void ParentData::getOp(CurrentOperatorPtr & ptr)
{
  ptr.parent=this;
}
inline void ParentData::getAcc(CurrentAccessPtr & ptr)
{
  ptr.parent=this;
}